home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 3 / CD ACTUAL 3.iso / linux / system / srouted-.000 / srouted- / srouted-0.1pl1 / table.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-17  |  11.9 KB  |  479 lines

  1. /* table.c -- table manipulation and IP address parsing */
  2.  
  3. /*
  4.  *  srouted -- silent routing daemon
  5.  *  Copyright (C) 1995 Kevin Buhr
  6.  *
  7.  *  This program is free software; you can redistribute it and/or modify
  8.  *  it under the terms of the GNU General Public License as published by
  9.  *  the Free Software Foundation; either version 2 of the License, or
  10.  *  (at your option) any later version.
  11.  *
  12.  *  This program is distributed in the hope that it will be useful,
  13.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  *  GNU General Public License for more details.
  16.  *
  17.  *  You should have received a copy of the GNU General Public License
  18.  *  along with this program; if not, write to the Free Software
  19.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  */
  21.  
  22. #ifndef lint
  23. static char rcsid[] = "$Id: table.c,v 1.3 1995/02/17 17:43:00 buhr Exp $";
  24. #endif /* not lint */
  25.  
  26. #include "defs.h"
  27. #include "kernel.h"
  28. #include "output.h"
  29. #include "timer.h"
  30. #include "table.h"
  31.  
  32. #include <netinet/in.h>
  33. #include <time.h>
  34. #include <string.h>
  35.  
  36. static int tb_route_free=0;
  37. static int tb_iface_free=0;
  38.  
  39. static void tb_ifdest( struct tb_iface *iface, struct sockaddr *dest );
  40. static int tb_ifroute( int ifi );
  41.  
  42.  
  43. /*
  44.  *    Get an empty interface table entry
  45.  */
  46.  
  47. int tb_newiface(void)
  48. {
  49.    int count=0;
  50.    struct tb_iface *iface;
  51.  
  52.    while( tb_iface[tb_iface_free].tbif_flags & TBIFF_USED ) {
  53.       tb_iface_free++;
  54.       if( ++count > TB_IFACE_SIZE )
  55.      return -1;
  56.    }
  57.    iface = &tb_iface[tb_iface_free];
  58.    iface->tbif_flags=0;
  59.  
  60.    return tb_iface_free;
  61. }
  62.  
  63.  
  64. /*
  65.  *    Get an empty route table entry
  66.  */
  67.  
  68. int tb_newroute(void)
  69. {
  70.    int count=0;
  71.    struct tb_route *route;
  72.  
  73.    while( tb_route[tb_route_free].tbrt_flags & TBRTF_USED ) {
  74.       tb_route_free++;
  75.       if( ++count > TB_ROUTE_SIZE )
  76.      return -1;
  77.    }
  78.    route = &tb_route[tb_route_free];
  79.    memset((void *) &route->tbrt_dst,0,sizeof(route->tbrt_dst));
  80.    memset((void *) &route->tbrt_mask,0,sizeof(route->tbrt_mask));
  81.    memset((void *) &route->tbrt_gateway,0,sizeof(route->tbrt_gateway));
  82.    route->tbrt_iface=-1;
  83.    route->tbrt_supernet=-1;
  84.    route->tbrt_metric=0;
  85.    route->tbrt_flags=0;
  86.    route->tbrt_timer=0;
  87.  
  88.    return tb_route_free;
  89. }
  90.  
  91.  
  92. /*
  93.  *    Convert a sockaddr structure into a host-order IP address
  94.  */
  95. unsigned long int tb_satoip( struct sockaddr *sa )
  96. {
  97.    return ntohl( ((struct sockaddr_in *) sa)->sin_addr.s_addr );
  98. }
  99.  
  100.  
  101. /*
  102.  *    Convert a host-order IP address to a sockaddr structure
  103.  */
  104. void tb_iptosa( unsigned long int a, struct sockaddr *sa )
  105. {
  106.    memset((void *) sa, 0, sizeof(struct sockaddr));
  107.    sa->sa_family = AF_INET;
  108.    ((struct sockaddr_in *) sa)->sin_addr.s_addr
  109.       = htonl(a);
  110. }
  111.  
  112.  
  113. /*
  114.  *    Get route table entry for given destination address
  115.  */
  116.  
  117. int tb_findroute(struct sockaddr *dst)
  118. {
  119.    int i;
  120.  
  121.    for(i=0; i<TB_ROUTE_SIZE; i++) {
  122.       if( (tb_route[i].tbrt_flags & TBRTF_USED) == 0 )
  123.      continue;
  124.       if( tb_samehost( &tb_route[i].tbrt_dst, dst ) )
  125.      return(i);
  126.    }
  127.  
  128.    return -1;
  129. }
  130.  
  131.  
  132. /*
  133.  *    Check if two sockaddrs refer to same network/host entity
  134.  *    (currently returns "false" for address families other than INET)
  135.  */
  136. int tb_samehost( struct sockaddr *a1, struct sockaddr *a2 )
  137. {
  138.    if( a1->sa_family == a2->sa_family
  139.       && a1->sa_family == AF_INET 
  140.       && tb_satoip(a1) == tb_satoip(a2) )
  141.       return 1;
  142.    else
  143.       return 0;
  144. }
  145.  
  146.  
  147. /*
  148.  *    Get destination address of an interface
  149.  */
  150.  
  151. static void tb_ifdest( struct tb_iface *iface, struct sockaddr *dest )
  152. {
  153.    char *p, *q;
  154.    int i;
  155.  
  156.    if( iface->tbif_flags & TBIFF_POINTOPOINT ) {
  157.       *dest = iface->tbif_dstaddr;
  158.    } else {
  159.       *dest = iface->tbif_myaddr;
  160.       p = (char *) &dest->sa_data;
  161.       q = (char *) &iface->tbif_netmask.sa_data;
  162.       for( i = 0; i < sizeof( iface->tbif_myaddr.sa_data ); i++ )
  163.      *p++ &= *q++; 
  164.    }
  165. }
  166.  
  167.  
  168. /*
  169.  *    Create routing supernet entry, if necessary
  170.  */
  171.  
  172. void tb_makesuper( int route, struct tb_address *dest )
  173. {
  174.    int super;
  175.  
  176.    if( dest->tba_flags & TBAF_SUBNET ) {
  177.       super = tb_findroute( &dest->tba_netsa );
  178.       if( super == -1 ) {
  179.      super = tb_newroute();
  180.      if(super==-1) {
  181.         warn0(ERCTB_RTFULL);
  182.         return;
  183.      }
  184.      tb_route[super].tbrt_dst = dest->tba_netsa;
  185.      tb_route[super].tbrt_mask = dest->tba_supmasksa;
  186.      tb_route[super].tbrt_metric = TBM_INFINITY;
  187.      tb_route[super].tbrt_flags = TBRTF_USED | TBRTF_KEEP
  188.         | TBRTF_KILLED | TBRTF_SUPERNET;
  189.      note1( ERCTB_ADDEDSUPER, super );
  190.       } else {
  191.      if( (tb_route[super].tbrt_flags & TBRTF_SUPERNET)==0 ) {
  192.         warn1( ERCTB_BADSUPER, &dest );
  193.      }
  194.       }
  195.       tb_route[route].tbrt_supernet = super;
  196.       tb_route[route].tbrt_flags |= TBRTF_SUBNET;
  197.    }
  198.  
  199. }
  200. /*
  201.  *    Construct default route table entry for an interface
  202.  */
  203.  
  204. static int tb_ifroute(int ifi)
  205. {
  206.    int rti;
  207.    struct tb_route *route;
  208.    struct tb_iface *iface;
  209.    struct tb_address dest;  /* route destination address */
  210.  
  211.    iface = &tb_iface[ifi];
  212.    if( iface->tbif_flags & TBIFF_LOOPBACK ) {
  213.       return 0;
  214.    }
  215.    tb_ifdest( iface, &dest.tba_addr );
  216.    tb_chkaddr(&dest);
  217.    if( (dest.tba_flags & TBAF_VALID) == 0 ) {
  218.       weakwarn2(ERCTB_INVDEST,iface,&dest);
  219.       return ERCTB_INVDEST;  /* bad destination */
  220.    }
  221.    rti = tb_findroute(&dest.tba_addr);
  222.    if( rti != -1 ) {
  223.       warn2(ERCTB_RTDUP,iface,&tb_route[rti]);
  224.       return ERCTB_RTDUP;
  225.    }
  226.    rti = tb_newroute();
  227.    if(rti==-1) {
  228.       warn0(ERCTB_RTFULL);
  229.       return ERCTB_RTFULL;
  230.    }
  231.    route=&tb_route[rti];
  232.    route->tbrt_dst=dest.tba_addr;
  233.    tb_iptosa( dest.tba_netmask, &route->tbrt_mask );
  234.    tb_iptosa( 0, &route->tbrt_gateway );  /* no gateway---direct route */
  235.    route->tbrt_iface=ifi;
  236.    route->tbrt_metric=tb_iface[ifi].tbif_metric;
  237.    /* may want to add TBRTF_TENTATIVE based on command line option */
  238.    route->tbrt_flags |= TBRTF_USED|TBRTF_DIRECT|TBRTF_KEEP;
  239.    if( dest.tba_flags & TBAF_HOST )
  240.       route->tbrt_flags |= TBRTF_HOST;
  241.    note2( ERCTB_IFDEFAULT, &tb_iface[ifi], route );
  242.    tb_makesuper( rti, &dest );
  243.  
  244.    return 0;
  245. }
  246.  
  247.  
  248. /*
  249.  *    Construct initial route table entries for interfaces
  250.  */
  251.  
  252. void tb_initroute(void)
  253. {
  254.    int ifi;
  255.  
  256.    for( ifi=0; ifi<TB_IFACE_SIZE; ifi++ ) {
  257.       if( tb_iface[ifi].tbif_flags & TBIFF_USED
  258.      && tb_iface[ifi].tbif_flags & TBIFF_UP ) {
  259.      tb_ifroute(ifi);
  260.       }
  261.    }
  262. }
  263.  
  264.  
  265. /*
  266.  *    Get our metric for this destination (infinity if no entry)
  267.  */
  268.  
  269. short tb_rtmetric(struct sockaddr dst)
  270. {
  271.    int rti;
  272.  
  273.    rti = tb_findroute(&dst);
  274.    if(rti==-1)
  275.       return TBM_INFINITY;
  276.    return tb_route[rti].tbrt_metric;
  277. }
  278.  
  279.  
  280. /*
  281.  *    Check/analyze an IP address
  282.  */
  283.  
  284. void tb_chkaddr(struct tb_address *a)
  285. {
  286.    int ifi;
  287.    unsigned long ah, myaddr, netmask;
  288.    int ifscore=0;
  289.    int ifguess=-1;
  290.  
  291.    a->tba_flags=0;
  292.    a->tba_iface=-1;
  293.    a->tba_af = a->tba_addr.sa_family;
  294.  
  295.    /* check it's an IP address */
  296.    if(a->tba_af != AF_INET) {
  297.       return;
  298.    }
  299.    a->tba_port = ntohs( ((struct sockaddr_in *) &a->tba_addr)->sin_port );
  300.    ah = ntohl( ((struct sockaddr_in *) &a->tba_addr)->sin_addr.s_addr );
  301.    if(ah==0x00000000) {
  302.       a->tba_flags|=TBAF_DEFAULT|TBAF_VALID;
  303.       a->tba_network=0;
  304.       a->tba_host=0;
  305.       a->tba_hostsa=a->tba_addr;
  306.       a->tba_subnet=0;
  307.       a->tba_subnetsa=a->tba_addr;
  308.       a->tba_netmask=0;
  309.       return;
  310.    }
  311.    if(IN_CLASSA(ah)) {
  312.       a->tba_flags|=TBAF_CLASSA;
  313.       a->tba_netmask=IN_CLASSA_NET;
  314.    } else if(IN_CLASSB(ah)) {
  315.       a->tba_flags|=TBAF_CLASSB;
  316.       a->tba_netmask=IN_CLASSB_NET;
  317.    } else if(IN_CLASSC(ah)) {
  318.       a->tba_flags|=TBAF_CLASSC;
  319.       a->tba_netmask=IN_CLASSC_NET;
  320.    } else {
  321.       return;  /* invalid address */
  322.    }
  323.    a->tba_flags|=TBAF_VALID;
  324.    a->tba_network = ah & a->tba_netmask;
  325.    tb_iptosa( a->tba_network, &a->tba_netsa );
  326.    tb_iptosa( a->tba_netmask, &a->tba_supmasksa );
  327.    /* find correct subnet */
  328.    for(ifi=0; ifi<TB_IFACE_SIZE; ifi++) {
  329.       if( (tb_iface[ifi].tbif_flags & TBIFF_USED)==0 ) {
  330.      continue;
  331.       }
  332.       if( tb_iface[ifi].tbif_myaddr.sa_family == AF_INET ) {
  333.      myaddr = tb_satoip( &tb_iface[ifi].tbif_myaddr );
  334.      /* is our network subnetted? */
  335.      netmask = tb_satoip( &tb_iface[ifi].tbif_netmask );
  336.      if( (myaddr & a->tba_netmask) == a->tba_network
  337.         && a->tba_netmask != netmask ) {
  338.         a->tba_netmask = netmask;
  339.         a->tba_flags |= TBAF_SUBNET;
  340.         break;
  341.      }
  342.       }
  343.    }
  344.    a->tba_subnet = ah & a->tba_netmask;
  345.    tb_iptosa( a->tba_subnet, &a->tba_subnetsa );
  346.    a->tba_host = ah & ~a->tba_netmask;
  347.    tb_iptosa( a->tba_subnet | a->tba_host, &a->tba_hostsa );
  348.    if(a->tba_host == ~a->tba_netmask) {
  349.       a->tba_flags|=TBAF_BROADCAST;
  350.    } else if(a->tba_host) {
  351.       a->tba_flags|=TBAF_HOST;
  352.    }
  353.  
  354.    /*
  355.     * The following block finds the interface most likely associated
  356.     * with the address giving preference to (in descending order):
  357.     *        - match to own address with interface to a network
  358.     *        - match to own address with point-to-point interface
  359.     *        - match to point-to-point destination address
  360.     *         - match to destination network
  361.     */
  362.    ifscore=0;
  363.    for(ifi=0; ifi<TB_IFACE_SIZE; ifi++) {
  364.       if( (tb_iface[ifi].tbif_flags & TBIFF_USED)==0 ) {
  365.      continue;
  366.       }
  367.       if( tb_iface[ifi].tbif_myaddr.sa_family == AF_INET ) {
  368.      myaddr = tb_satoip( &tb_iface[ifi].tbif_myaddr );
  369.      /* if on same subnet, these interface scores apply... */
  370.      if( (myaddr & a->tba_netmask) == a->tba_subnet ) {
  371.         /* if it's our own address... */
  372.         if( (a->tba_flags & TBAF_HOST) 
  373.            && (myaddr & ~a->tba_netmask) == a->tba_host ) {
  374.            if(tb_iface[ifi].tbif_flags & TBIFF_POINTOPOINT) {
  375.           /* score 3 for own address on point-to-point */
  376.           if(ifscore<3) {
  377.              ifscore=3;
  378.              ifguess=ifi;
  379.           }
  380.            } else {
  381.           /* score 4 for own address on network interface */
  382.           if(ifscore<4) {
  383.              ifscore=4;
  384.              ifguess=ifi;
  385.           }
  386.            }
  387.         }
  388.         /* score 1 for address on a network interface */
  389.         else {
  390.            if(ifscore<1) {
  391.           ifscore=1;
  392.           ifguess=ifi;
  393.            }
  394.         }
  395.      } else {
  396.         /* check point-to-point destination */
  397.         if( (a->tba_flags & TBAF_HOST)
  398.            && (tb_iface[ifi].tbif_flags & TBIFF_POINTOPOINT)
  399.            && tb_satoip(&tb_iface[ifi].tbif_dstaddr)
  400.                         == tb_satoip(&a->tba_addr) ) {
  401.            /* score 2 for point-to-point destination */
  402.            if(ifscore<2) {
  403.           ifscore=2;
  404.           ifguess=ifi;
  405.            }
  406.         }
  407.      }
  408.       }
  409.    }
  410.  
  411.    if(ifscore>0)
  412.       a->tba_iface=ifguess;
  413.  
  414. }
  415.  
  416.  
  417. /*
  418.  *    Add a route to the table
  419.  */
  420.  
  421. void tb_addroute( int route, struct tb_address *dest, 
  422.          struct tb_address *gw, short cost )
  423. {
  424.    tb_route[route].tbrt_flags |= TBRTF_CHANGED | TBRTF_USED;
  425.    tb_route[route].tbrt_flags &= 
  426.       ~(TBRTF_TENTATIVE|TBRTF_KILLED|TBRTF_DELETED);
  427.    tb_route[route].tbrt_dst = dest->tba_hostsa;
  428.    if( dest->tba_flags & TBAF_HOST )
  429.       tb_route[route].tbrt_flags |= TBRTF_HOST;
  430.    tb_makesuper( route, dest );
  431.    tb_iptosa( dest->tba_netmask, &tb_route[route].tbrt_mask );
  432.    tb_route[route].tbrt_gateway = gw->tba_hostsa;
  433.    tb_route[route].tbrt_metric = cost;
  434.    /* default routes should be hard to lose */
  435.    if( dest->tba_flags & TBAF_DEFAULT )
  436.       tb_route[route].tbrt_flags |= TBRTF_KEEP | TBRTF_DEFAULT;
  437.    note1( ERCTB_ADDRT, route );
  438.    tm_settimeout( route );
  439.    kr_addroute( route );
  440.    out_update( route );
  441. }
  442.  
  443.  
  444. /*
  445.  *    Delete a route from the table
  446.  */
  447.  
  448. void tb_delroute( int route, struct tb_address *gw )
  449. {
  450.    tb_route[route].tbrt_flags &= ~(TBRTF_TENTATIVE|TBRTF_KILLED);
  451.    tb_route[route].tbrt_flags |= (TBRTF_CHANGED|TBRTF_DELETED);
  452.    if(gw) tb_route[route].tbrt_gateway = gw->tba_hostsa;
  453.    tb_route[route].tbrt_metric = TBM_INFINITY;
  454.    note1( ERCTB_DELRT, route );
  455.    tm_setgarbcoll( route );
  456.    if( (tb_route[route].tbrt_flags & TBRTF_KEEP)==0 )
  457.       kr_delroute( route );
  458.    out_update( route );
  459. }
  460.  
  461.  
  462. /*
  463.  *    Kill a route from the table
  464.  */
  465.  
  466. void tb_killroute( int route )
  467. {
  468.    if( tb_route[route].tbrt_flags & TBRTF_KEEP ) {
  469.       note1( ERCTB_KEPTRT, route );
  470.       tb_route[route].tbrt_flags &= 
  471.      ~(TBRTF_CHANGED|TBRTF_DELETED);
  472.       tb_route[route].tbrt_flags |= TBRTF_KILLED;
  473.       tm_killtimer( route );
  474.    } else {
  475.       note1( ERCTB_KILLRT, route );
  476.       tb_route[route].tbrt_flags = 0;
  477.    }
  478. }
  479.